<?php

/**
 * 接口的基类
 *
 * @package core
 */
class DAO {
	private $dbname;
    function __construct() {
		$this->setdbname();
	}

    function __destruct() {}

    /*     * ***************** get db and cache config **************** */
	protected static function setdbname(){
		$conf=&load_conf("pub:db");
		if(!$conf) return false;

		if(isset($conf["dbmap"])){
			$dbnames=array_keys($conf["dbmap"]);
			$this->dbname=$dbnames[0];
		}
	
	}


    protected static function dbhash($hashid = 0, $tbname = "")
	{
		GLOBAL $__core_env;
		$dbname=$this->dbname;
		if (!$dbname || !$tbname) return false;
		
		$conf = &load_conf("pub:db");
		if (!$conf) return false;
		
		$ret = array();
		if (isset($conf["dbmap"][$dbname]))
		{
			$sp = array();
			$db = $conf["dbmap"][$dbname];
                        
			if (is_array($db))
			{
				$sp['dbsp'] = intval($db['dbsp']);
				$sp['tbsp'] = intval($db['tables'][$tbname]);
                                
				if ($db["servers"])
				{
					foreach ($db["servers"] as $n => $idx)
					{       
						if ($hashid <= $n * 10000 && isset($conf["dbserver"][$idx]))
						{
							$ret = $conf["dbserver"][$idx];
							break;
						}
					}
				}
				else $ret = $conf["dbserver"][intval($db["servers"])];
				
				if ($ret && ($sp['dbsp'] || $sp['tbsp']))
				{
					$hashmd5 = md5($hashid);
					$hash1 = substr($hashmd5, 0, 2);
					$hash2 = substr($hashmd5, 2, 2);
					$ret[3] = $sp['dbsp'] ? $dbname . '_' . hexdec($hash1) % $sp['dbsp'] : $dbname;
					$ret[4] = $sp['tbsp'] ? $tbname . '_' . hexdec($hash2) % $sp['tbsp'] : $tbname;
				}
				elseif ($ret)
				{
					$ret[3] = $dbname;
					$ret[4] = $tbname;
				}
			}
		}
                
		return $ret;
    }

    protected static function mchash($key = "", $hashid = 0)
	{
		GLOBAL $__core_env;
		$conf = &load_conf("pub:db");
		if (!$conf) return false;
		
		$ret = array();
		if (isset($conf["mcmap"][$key]))
		{
			if (is_array($conf["mcmap"][$key]["servers"]))
			{
				foreach ($conf["mcmap"][$key]["servers"] as $n => $idx)
				{
					if ($hashid <= $n * 10000 && isset($conf["mcserver"][$idx]))
					{
						$ret = $conf["mcserver"][$idx];
						break;
					}
				}
			}
			else
			{
				$idx = intval($conf["mcmap"][$key]["servers"]);
				if (isset($conf["mcserver"][$idx])) $ret = $conf["mcserver"][$idx];
			}
		}
		return $ret;
    }

    protected static function zbin(&$in_arr = array())
	{
		if (is_array($in_arr)) return serialize($in_arr);
		else return $in_arr;
    }

    protected static function unzbin(&$in_bin = "")
	{
		return unserialize($in_bin);
    }

    /*     * ****************** db api ***************** */

    protected static function dbconnect($host, $user, $pass, $db)
	{
		$conn = @mysql_connect($host, $user, $pass);
		if (!is_resource($conn))
		{
			self::daoerrlog("dbconn,{$user},{$host},{$db}");
			return false;
		}
		@mysql_query("set names 'utf8'", $conn);
		self::dbuse($conn, $db);
		return $conn;
    }

    protected static function dbuse($conn, $db)
	{
		if (!is_resource($conn) || !$db) return false;
		@mysql_select_db($db, $conn);
    }

    protected static function dbquery($conn, $sql, $rettype = 'result')
	{
		$result = @mysql_query($sql, $conn);
		if (!$result) return false;

		switch ($rettype)
		{
			case "result":
				return $result;
				break;

			case "row":
				if ($result && mysql_num_rows($result) == 1) return mysql_fetch_assoc($result);
				elseif($result) return array();
				else return false;
				break;

			case "rows":
				if ($result && mysql_num_rows($result) >= 1)
				{
					while ($row = mysql_fetch_assoc($result))  $rows[] = $row;
					unset($row);
					return $rows;
				}
				elseif($result) return array();
				else return false;
				break;

			case "value":
				if ($result && mysql_num_rows($result) == 1)
				{
					$row = mysql_fetch_row($result);
					return $row[0];
				}
				elseif($result) return "";
				else return false;
				break;

			default: return false;
		}
    }

    protected static function dbid($conn){ return @mysql_insert_id($conn); }

    protected static function dbclose($conn)
	{
		if (is_resource($conn)) @mysql_close($conn);
    }

    /**
     * 发送错误日志记录
     * 
     */
    protected static function daoerrlog($content = "")
	{
		if (!($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))) return false;
	
		socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array(
			"sec" => UDP_TIMEOUT_SEC, 
			"usec" => UDP_TIMEOUT_USEC
			));
		socket_sendto($socket, $content, strlen($content), 0, DAO_ERRLOG_HOST, DAO_ERRLOG_PORT);
		socket_close($socket);
    }

    /**
     * 数据库连接类，返回一个连接
     */
    protected static function getconn($uid = 0, &$dbconf = array(), $funame = "")
	{
		if (!$dbconf) return false;
		
		$dbconn = self::dbconnect($dbconf[0], $dbconf[1], $dbconf[2], $dbconf[3]);
		if (!is_resource($dbconn)) return false;
		
		return $dbconn;
    }

    /**
     * 从缓存中读数据，有结果返回值，无结果返回false
     */
    protected static function getcache($uid = 0, &$mcconf = array(), $mck = "", $db = 0, $funame = "")
	{
		if (!$db)
		{
			$rs = get_global("mc:{$mck}");
			if ($rs) return $rs;
		}
		if (!$mcconf) return false;
		
		if (!$db && $mcconf)
		{
			$mc = new Memcache;
			if (!@$mc->connect($mcconf[0], $mcconf[1]))
			{
				self::daoerrlog("mcconn,{$mcconf[0]},{$mcconf[1]}");
				return false;
			}

			$rs = @$mc->get($mck);
			@$mc->close();
			if ($rs) return $rs;
		}
		return false;
    }

    /**
     * 设置memcache中缓存
     */
    protected static function setcache($uid = 0, &$mcconf = array(), $mck = "", &$rs = array(), $funame = "")
	{
		$mc = new Memcache;
		if (!@$mc->connect($mcconf[0], $mcconf[1]) || !@$mc->set($mck, $rs, 0, 86400))
		{
			self::daoerrlog("mcconn,{$mcconf[0]},{$mcconf[1]}");
			return false;
		}
		@$mc->close();
		return true;
    }

    /**
     * 清除缓存
     */
    protected static function delcache($uid = 0, &$mcconf = array(), $mck = "", $funame = "")
	{
		if (!$mcconf) return false;
		
		$mc = new Memcache;
		if (!@$mc->connect($mcconf[0], $mcconf[1]))
		{
			self::daoerrlog("mcconn,{$mcconf[0]},{$mcconf[1]}");
			return false;
		}
		if(is_array($mck))
		{
			foreach($mck as $k) @$mc->delete($k);
		}
		else @$mc->delete($mck);
		@$mc->close();
		del_global("mc:{$mck}");
		return true;
    }

}
